
%{

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <stdexcept>
#include <utility>

#include "common/log/log.h"
#include "common/lang/string.h"
#include "sql/parser/parse_defs.h"
#include "sql/parser/yacc_sql.hpp"
#include "sql/parser/lex_sql.h"
#include "sql/parser/date.h"
#include "sql/expr/expression.h"

using namespace std;

string token_name(const char *sql_string, YYLTYPE *llocp)
{
  return string(sql_string + llocp->first_column, llocp->last_column - llocp->first_column + 1);
}

int yyerror(YYLTYPE *llocp, const char *sql_string, ParsedSqlResult *sql_result, yyscan_t scanner, const char *msg)
{
  std::unique_ptr<ParsedSqlNode> error_sql_node = std::make_unique<ParsedSqlNode>(SCF_ERROR);
  error_sql_node->error.error_msg = msg;
  error_sql_node->error.line = llocp->first_line;
  error_sql_node->error.column = llocp->first_column;
  sql_result->add_sql_node(std::move(error_sql_node));
  return 0;
}

ArithmeticExpr *create_arithmetic_expression(ArithmeticExpr::Type type,
                                             Expression *left,
                                             Expression *right,
                                             const char *sql_string,
                                             YYLTYPE *llocp)
{
  ArithmeticExpr *expr = new ArithmeticExpr(type, left, right);
  expr->set_name(token_name(sql_string, llocp));
  return expr;
}

UnboundAggregateExpr *create_aggregate_expression(const char *aggregate_name,
                                           Expression *child,
                                           const char *sql_string,
                                           YYLTYPE *llocp)
{
  UnboundAggregateExpr *expr = new UnboundAggregateExpr(aggregate_name, child);
  expr->set_name(token_name(sql_string, llocp));
  return expr;
}

%}

%define api.pure full
%define parse.error verbose
/** 启用位置标识 **/
%locations
%lex-param { yyscan_t scanner }
/** 这些定义了在yyparse函数中的参数 **/
%parse-param { const char * sql_string }
%parse-param { ParsedSqlResult * sql_result }
%parse-param { void * scanner }

//标识tokens
%token  SEMICOLON
        BY
        CREATE
        DROP
        GROUP
        JOIN
        INNER
        COUNT
        SUM
        AVG
        MAX
        MIN
        TABLE
        TABLES
        INDEX
        UNIQUE
        CALC
        SELECT
        DESC
        SHOW
        SYNC
        INSERT
        DELETE
        UPDATE
        LBRACE
        RBRACE
        COMMA
        TRX_BEGIN
        TRX_COMMIT
        TRX_ROLLBACK
        INT_T
        DATE_T
        STRING_T
        FLOAT_T
        VECTOR_T
        HELP
        EXIT
        DOT //QUOTE
        INTO
        VALUES
        FROM
        WHERE
        AND
        SET
        ON
        NULL_T
        LOAD
        DATA
        INFILE
        EXPLAIN
        STORAGE
        FORMAT
        EQ
        LIKE
        NOT
        LT
        GT
        LE
        GE
        NE
        IS_
        IN
        EXISTS
        LENGTH_FUNCTION
        ROUND_FUNCTION
        DATE_FORMAT_FUNCTION
        AS
        TEXT
        ORDER
        ASC
        HAVING
        OR
        

/** union 中定义各种数据类型，真实生成的代码也是union类型，所以不能有非POD类型的数据 **/
%union {
  ParsedSqlNode *                            sql_node;
  ConditionSqlNode *                         condition;
  Value *                                    value;
  enum CompOp                                comp;
  RelAttrSqlNode *                           rel_attr;
  std::vector<AttrInfoSqlNode> *             attr_infos;
  AttrInfoSqlNode *                          attr_info;
  Expression *                               expression;
  std::vector<std::unique_ptr<Expression>> * expression_list;
  // std::vector<Value> *                       value_list;
  std::vector<ConditionSqlNode> *            condition_list;
  std::vector<RelAttrSqlNode> *              rel_attr_list;
  UpdateInfoSqlNode *                        update_list;
  std::vector<std::pair<std::string, std::string>> *                 relation_list;
  InnerJoinSqlNode *                         inner_join_list;
  char *                                     string;
  int                                        number;
  float                                      floats;
  std::pair<RelAttrSqlNode *, bool> *        order_by;
  std::vector<std::pair<RelAttrSqlNode *, bool>> * order_by_list;
  std::vector<std::pair<RelAttrSqlNode *, bool>> * order_by_stmt;
  GroupBySqlNode *                           group_by;
  bool *                                     conjunction_op;

}

%token <number> NUMBER
%token <floats> FLOAT
%token <string> ID
%token <string> DATE_SSS
%token <string> SSS
//非终结符

/** type 定义了各种解析后的结果输出的是什么类型。类型对应了 union 中的定义的成员变量名称 **/
%type <number>              type
%type <condition>           condition
%type <value>               value
%type <number>              number
%type <string>              relation
%type <comp>                comp_op
%type <rel_attr>            rel_attr
%type <attr_infos>          attr_def_list
%type <attr_info>           attr_def
/* %type <rel_attr_list>       rel_attr_list */
// %type <value_list>          value_list
%type <condition_list>      where
%type <condition_list>      condition_list
%type <condition_list>      on_condition
%type <string>              storage_format
%type <relation_list>       rel_list
%type <update_list>         update_list
%type <expression>          expression
%type <expression_list>     expression_list
%type <group_by>            group_by
%type <expression_list>     group_by_list
%type <inner_join_list>     inner_join_list
%type <sql_node>            calc_stmt
%type <sql_node>            select_stmt
%type <sql_node>            insert_stmt
%type <sql_node>            update_stmt
%type <sql_node>            delete_stmt
%type <sql_node>            create_table_stmt
%type <sql_node>            drop_table_stmt
%type <sql_node>            show_tables_stmt
%type <sql_node>            desc_table_stmt
%type <sql_node>            create_index_stmt
%type <sql_node>            drop_index_stmt
%type <sql_node>            sync_stmt
%type <sql_node>            begin_stmt
%type <sql_node>            commit_stmt
%type <sql_node>            rollback_stmt
%type <sql_node>            load_data_stmt
%type <sql_node>            explain_stmt
%type <sql_node>            set_variable_stmt
%type <sql_node>            help_stmt
%type <sql_node>            exit_stmt
%type <sql_node>            command_wrapper
// commands should be a list but I use a single command instead
%type <sql_node>            commands
%type <string>              alias_stmt
%type <order_by>            order_by
%type <order_by_list>       order_by_list
%type <order_by_stmt>       order_by_stmt
%type <conjunction_op>      conjunction_op

%left '+' '-'
%left '*' '/'
%left COUNT AVG SUM MAX MIN
%nonassoc UMINUS
%%

commands: command_wrapper opt_semicolon  //commands or sqls. parser starts here.
  {
    std::unique_ptr<ParsedSqlNode> sql_node = std::unique_ptr<ParsedSqlNode>($1);
    sql_result->add_sql_node(std::move(sql_node));
  }
  ;

command_wrapper:
    calc_stmt
  | select_stmt
  | insert_stmt
  | update_stmt
  | delete_stmt
  | create_table_stmt
  | drop_table_stmt
  | show_tables_stmt
  | desc_table_stmt
  | create_index_stmt
  | drop_index_stmt
  | sync_stmt
  | begin_stmt
  | commit_stmt
  | rollback_stmt
  | load_data_stmt
  | explain_stmt
  | set_variable_stmt
  | help_stmt
  | exit_stmt
    ;

exit_stmt:      
    EXIT {
      (void)yynerrs;  // 这么写为了消除yynerrs未使用的告警。如果你有更好的方法欢迎提PR
      $$ = new ParsedSqlNode(SCF_EXIT);
    };

help_stmt:
    HELP {
      $$ = new ParsedSqlNode(SCF_HELP);
    };

sync_stmt:
    SYNC {
      $$ = new ParsedSqlNode(SCF_SYNC);
    }
    ;

begin_stmt:
    TRX_BEGIN  {
      $$ = new ParsedSqlNode(SCF_BEGIN);
    }
    ;

commit_stmt:
    TRX_COMMIT {
      $$ = new ParsedSqlNode(SCF_COMMIT);
    }
    ;

rollback_stmt:
    TRX_ROLLBACK  {
      $$ = new ParsedSqlNode(SCF_ROLLBACK);
    }
    ;

drop_table_stmt:    /*drop table 语句的语法解析树*/
    DROP TABLE ID {
      $$ = new ParsedSqlNode(SCF_DROP_TABLE);
      $$->drop_table.relation_name = $3;
      free($3);
    };

show_tables_stmt:
    SHOW TABLES {
      $$ = new ParsedSqlNode(SCF_SHOW_TABLES);
    }
    ;

desc_table_stmt:
    DESC ID  {
      $$ = new ParsedSqlNode(SCF_DESC_TABLE);
      $$->desc_table.relation_name = $2;
      free($2);
    }
    ;

create_index_stmt:    /*create index 语句的语法解析树*/
    // 这里的rel_list只是借用了它的语法规则，实际上含义应该是attr_list
    CREATE INDEX ID ON ID LBRACE rel_list RBRACE
    {
      $$ = new ParsedSqlNode(SCF_CREATE_INDEX);
      CreateIndexSqlNode &create_index = $$->create_index;
      create_index.unique = false;
      create_index.index_name = $3;
      create_index.relation_name = $5;
      /* create_index.attribute_name = $7; */
      for(unsigned i = 0; i < $7->size(); i++){
        create_index.attribute_names.push_back((*$7)[i].first);
      }
      std::sort(create_index.attribute_names.begin(), create_index.attribute_names.end());
      free($3);
      free($5);
      /* free($7); */
      delete $7;
    }
    | CREATE UNIQUE INDEX ID ON ID LBRACE rel_list RBRACE
    {
      $$ = new ParsedSqlNode(SCF_CREATE_INDEX);
      CreateIndexSqlNode &create_index = $$->create_index;
      create_index.unique = true;
      create_index.index_name = $4;
      create_index.relation_name = $6;
      /* create_index.attribute_name = $8; */
      for(unsigned i = 0; i < $8->size(); i++){
        create_index.attribute_names.push_back((*$8)[i].first);
      }
      std::sort(create_index.attribute_names.begin(), create_index.attribute_names.end());
      free($4);
      free($6);
      /* free($8); */
      delete $8;
    }
    ;

drop_index_stmt:      /*drop index 语句的语法解析树*/
    DROP INDEX ID ON ID
    {
      $$ = new ParsedSqlNode(SCF_DROP_INDEX);
      $$->drop_index.index_name = $3;
      $$->drop_index.relation_name = $5;
      free($3);
      free($5);
    }
    ;
create_table_stmt:    /*create table 语句的语法解析树*/
    CREATE TABLE ID LBRACE attr_def attr_def_list RBRACE storage_format
    {
      $$ = new ParsedSqlNode(SCF_CREATE_TABLE);
      CreateTableSqlNode &create_table = $$->create_table;
      create_table.relation_name = $3;
      free($3);

      std::vector<AttrInfoSqlNode> *src_attrs = $6;

      if (src_attrs != nullptr) {
        create_table.attr_infos.swap(*src_attrs);
        delete src_attrs;
      }
      create_table.attr_infos.emplace_back(*$5);
      std::reverse(create_table.attr_infos.begin(), create_table.attr_infos.end());
      delete $5;
      if ($8 != nullptr) {
        create_table.storage_format = $8;
        free($8);
      }
    }
    | CREATE TABLE ID AS select_stmt{
      $$ = new ParsedSqlNode(SCF_CREATE_TABLE);
      CreateTableSqlNode &create_table = $$->create_table;
      create_table.relation_name = $3;
      free($3);
      SubQueryExpr *sub_query_expr = new SubQueryExpr($5->selection);
      create_table.select_expr = std::unique_ptr<Expression>(sub_query_expr);
    }
    | CREATE TABLE ID select_stmt{
      $$ = new ParsedSqlNode(SCF_CREATE_TABLE);
      CreateTableSqlNode &create_table = $$->create_table;
      create_table.relation_name = $3;
      free($3);
      SubQueryExpr *sub_query_expr = new SubQueryExpr($4->selection);
      create_table.select_expr = std::unique_ptr<Expression>(sub_query_expr);
    }
    | CREATE TABLE ID LBRACE attr_def attr_def_list RBRACE storage_format AS select_stmt
    {
      $$ = new ParsedSqlNode(SCF_CREATE_TABLE);
      CreateTableSqlNode &create_table = $$->create_table;
      create_table.relation_name = $3;
      free($3);

      std::vector<AttrInfoSqlNode> *src_attrs = $6;

      if (src_attrs != nullptr) {
        create_table.attr_infos.swap(*src_attrs);
        delete src_attrs;
      }
      create_table.attr_infos.emplace_back(*$5);
      std::reverse(create_table.attr_infos.begin(), create_table.attr_infos.end());
      delete $5;
      if ($8 != nullptr) {
        create_table.storage_format = $8;
        free($8);
      }
      SubQueryExpr *sub_query_expr = new SubQueryExpr($10->selection);
      create_table.select_expr = std::unique_ptr<Expression>(sub_query_expr);
    }
    | CREATE TABLE ID LBRACE attr_def attr_def_list RBRACE storage_format select_stmt
    {
      $$ = new ParsedSqlNode(SCF_CREATE_TABLE);
      CreateTableSqlNode &create_table = $$->create_table;
      create_table.relation_name = $3;
      free($3);

      std::vector<AttrInfoSqlNode> *src_attrs = $6;

      if (src_attrs != nullptr) {
        create_table.attr_infos.swap(*src_attrs);
        delete src_attrs;
      }
      create_table.attr_infos.emplace_back(*$5);
      std::reverse(create_table.attr_infos.begin(), create_table.attr_infos.end());
      delete $5;
      if ($8 != nullptr) {
        create_table.storage_format = $8;
        free($8);
      }
      SubQueryExpr *sub_query_expr = new SubQueryExpr($9->selection);
      create_table.select_expr = std::unique_ptr<Expression>(sub_query_expr);
    }
    ;
attr_def_list:
    /* empty */
    {
      $$ = nullptr;
    }
    | COMMA attr_def attr_def_list
    {
      if ($3 != nullptr) {
        $$ = $3;
      } else {
        $$ = new std::vector<AttrInfoSqlNode>;
      }
      $$->emplace_back(*$2);
      delete $2;
    }
    ;
    
attr_def:
    ID type LBRACE number RBRACE 
    {
      $$ = new AttrInfoSqlNode;
      $$->type = (AttrType)$2;
      $$->name = $1;
      $$->length = $4;
      $$->nullable = true;
      free($1);
    }
    | ID type
    {
      $$ = new AttrInfoSqlNode;
      $$->type = (AttrType)$2;
      $$->name = $1;
      $$->length = 4;
      $$->nullable = true;
      free($1);
    }
    |ID type LBRACE number RBRACE NOT NULL_T /* 这里和下面都添加了对于NULL的判断，如果不加对NULL的说明，默认是不能为NULL */
    {
      $$ = new AttrInfoSqlNode;
      $$->type = (AttrType)$2;
      $$->name = $1;
      $$->length = $4;
      $$->nullable = false;
      free($1);
    }
    | ID type NOT NULL_T
    {
      $$ = new AttrInfoSqlNode;
      $$->type = (AttrType)$2;
      $$->name = $1;
      $$->length = 4;
      $$->nullable = false;
      free($1);
    }
    |ID type LBRACE number RBRACE NULL_T
    {
      $$ = new AttrInfoSqlNode;
      $$->type = (AttrType)$2;
      $$->name = $1;
      $$->length = $4;
      $$->nullable = true;
      free($1);
    }
    | ID type NULL_T
    {
      $$ = new AttrInfoSqlNode;
      $$->type = (AttrType)$2;
      $$->name = $1;
      $$->length = 4;
      $$->nullable = true;
      free($1);
    }
    | ID TEXT /* TEXT类型默认长度为65535，且只能为NULL */
    {
      $$ = new AttrInfoSqlNode;
      $$->type = (AttrType)AttrType::CHARS;
      $$->name = $1;
      $$->length = 65580;  //考虑到bitmap的问题，比65535稍微大一点
      $$->nullable = true;
      free($1);
    }
    ;
number:
    NUMBER {$$ = $1;}
    ;
type:
    INT_T      { $$ = static_cast<int>(AttrType::INTS); }
    | STRING_T { $$ = static_cast<int>(AttrType::CHARS); }
    | FLOAT_T  { $$ = static_cast<int>(AttrType::FLOATS); }
    | VECTOR_T { $$ = static_cast<int>(AttrType::VECTORS); }
    | DATE_T   { $$ = static_cast<int>(AttrType::DATES); }
    ;
insert_stmt:        /*insert   语句的语法解析树*/
    INSERT INTO ID VALUES LBRACE expression_list RBRACE 
    {
      $$ = new ParsedSqlNode(SCF_INSERT);
      $$->insertion.relation_name = $3;
      if ($6 != nullptr) {
        for(unsigned i = 0;i < $6->size();i++){
          Expression *expr_tmp = (*$6)[i].get();
          Value value_tmp;
          expr_tmp->try_get_value(value_tmp);
          $$->insertion.values.push_back(value_tmp);
        }
        delete $6;
      }
      // std::reverse($$->insertion.values.begin(), $$->insertion.values.end());
      free($3);
    }
    ;

// value_list:
//     /* empty */
//     {
//       $$ = nullptr;
//     }
//     | COMMA value value_list  { 
//       if ($3 != nullptr) {
//         $$ = $3;
//       } else {
//         $$ = new std::vector<Value>;
//       }
//       $$->emplace_back(*$2);
//       delete $2;
//     }
//     ;
value:
    NUMBER {
      $$ = new Value((int)$1);
      @$ = @1;
    }
    |DATE_SSS{
      // 这里需要做一些修改，DATE_SSS原本是一个char*字符串，将其转换为string类型
      std::string val($1);

      // 去掉左右的引号
      val = val.substr(1, val.size() - 2);

      // date_to_int
      int date_int = string_to_int(val);
      if(!is_valid(date_int)){
        LOG_ERROR("invalid date input, date:%s", $1);
        $$ = new Value((int)date_int, 0);
        throw std::invalid_argument("Date invalid!");
      }
      else{
        LOG_INFO("Valid date! date:%s", $1);
        $$ = new Value((int)date_int, 0);
      }
      @$ = @1;    // 报告位置信息
    }
    |FLOAT {
      $$ = new Value((float)$1);
      @$ = @1;
    }
    |SSS {
      char *tmp = common::substr($1,1,strlen($1)-2);
      $$ = new Value(tmp);
      free(tmp);
      free($1);
    }
    |NULL_T {
      $$ = new Value();
      $$->set_null_flag(true);
    }
    ;
storage_format:
    /* empty */
    {
      $$ = nullptr;
    }
    | STORAGE FORMAT EQ ID
    {
      $$ = $4;
    }
    ;
    
delete_stmt:    /*  delete 语句的语法解析树*/
    DELETE FROM ID where 
    {
      $$ = new ParsedSqlNode(SCF_DELETE);
      $$->deletion.relation_name = $3;
      if ($4 != nullptr) {
        $$->deletion.conditions.swap(*$4);
        delete $4;
      }
      free($3);
    }
    ;
update_stmt:      /*  update 语句的语法解析树*/
    UPDATE ID SET update_list where
    {
      $$ = new ParsedSqlNode(SCF_UPDATE);
      $$->update.relation_name = $2;
      if(nullptr != $4){
        $$->update.attribute_name.swap($4->attribute_name);
        $$->update.value_exprs.swap($4->value_exprs);
      }
      if ($5 != nullptr) {
        $$->update.conditions.swap(*$5);
        delete $5;
      }
      free($2);
      delete $4;
    }
    ;

update_list:
    ID EQ expression
    {
      $$ = new UpdateInfoSqlNode;
      std::string ss = $1;
      $$->attribute_name.push_back(ss);
      $$->value_exprs.emplace_back($3);
      free($1);
    }
    | ID EQ expression COMMA update_list
    {
      if($5 != nullptr){
        $$ = $5;
      }
      std::string ss = $1;
      $$->attribute_name.push_back(ss);
      $$->value_exprs.emplace_back($3);
      free($1);
    }
    ;
select_stmt:        /*  select 语句的语法解析树*/
    SELECT expression_list FROM rel_list where group_by order_by_stmt
    {
      $$ = new ParsedSqlNode(SCF_SELECT);
      if ($2 != nullptr) {
        $$->selection.expressions.swap(*$2);
        delete $2;
      }

      if ($4 != nullptr) {
        $$->selection.relations_and_aliases.swap(*$4);
        delete $4;
      }

      if ($5 != nullptr) {
        $$->selection.conditions.swap(*$5);
        delete $5;
      }

      if ($6 != nullptr) {
        if($6->group_by != nullptr){
          $$->selection.group_by.swap(*($6->group_by));
          delete $6->group_by;
        }
        if($6->having != nullptr){
          $$->selection.having.swap(*($6->having));
          delete $6->having;
        }
        delete $6;
      }
      if ($7 != nullptr) {
        for (unsigned i = 0; i < $7->size(); i++) {
          RelAttrSqlNode  *node = (*$7)[i].first;
          bool is_asc = (*$7)[i].second;
          unique_ptr<Expression> unbound_field_expr(static_cast<Expression *>(new UnboundFieldExpr(node->relation_name, node->attribute_name)));
          std::unique_ptr<Expression> order_by_expr(static_cast<Expression *>(new OrderByExpr(std::move(unbound_field_expr), is_asc)));
          $$->selection.order_by.push_back(std::move(order_by_expr));
          delete node;
        }
        delete $7;
      }
    }
    /* | SELECT expression_list FROM relation INNER JOIN relation ON condition_list where { */
    /*   /\* TODO */
    /*    * 填充行为 */
    /*    *\/ */
    /*   $$ = new ParsedSqlNode(SCF_SELECT); */
    /*   if($2 != nullptr){ */
    /*     $$->selection.expressions.swap(*$2); */
    /*     delete $2; */
    /*   } */
    /*   $$->selection.relations.push_back($4); */
    /*   $$->selection.relations.push_back($7); */
    /*   if($9 != nullptr){ */
    /*     $$->selection.conditions.swap(*$9); */
    /*     delete $9; */
    /*   } */
    /*   if($10 != nullptr){ */
    /*     for(int i = 0; i < static_cast<int>($10->size()); i++){ */
    /*       $$->selection.conditions.push_back((*$10)[i]); */
    /*     } */
    /*     delete $10; */
    /*   } */
    /* } */
    | SELECT expression_list FROM relation alias_stmt inner_join_list where order_by_stmt{
      $$ = new ParsedSqlNode(SCF_SELECT);
      if($2 != nullptr){
        $$->selection.expressions.swap(*$2);
        delete $2;
      }
      // std::string s_tmp($4);
      if($5 == nullptr){
        std::pair<std::string, std::string> s_tmp($4, $4);
        $$->selection.relations_and_aliases.push_back(s_tmp);
      }
      else{
        std::pair<std::string, std::string> s_tmp($4, $5);
        $$->selection.relations_and_aliases.push_back(s_tmp);
        free($5);
      }
      free($4);
      for(unsigned i = 0; i < $6->relations_and_aliases.size(); i++){
        $$->selection.relations_and_aliases.push_back($6->relations_and_aliases[i]);
      }
      for(unsigned i = 0; i < $6->conditions.size();i++){
        $$->selection.conditions.push_back(std::move($6->conditions[i]));
      }
      delete $6;
      if(nullptr != $7){
        for (unsigned i = 0; i < $7->size(); i++) {
          $$->selection.conditions.push_back(std::move((*$7)[i]));
        }
        delete $7;
      }
      if ($8 != nullptr) {
        for (unsigned i = 0; i < $8->size(); i++) {
          RelAttrSqlNode  *node = (*$8)[i].first;
          bool is_asc = (*$8)[i].second;
          std::unique_ptr<Expression> unbound_field_expr(static_cast<Expression *>(new UnboundFieldExpr(node->relation_name, node->attribute_name)));
          std::unique_ptr<Expression> order_by_expr(static_cast<Expression *>(new OrderByExpr(std::move(unbound_field_expr), is_asc)));
          $$->selection.order_by.push_back(std::move(order_by_expr));
          delete node;
        }
        delete $8;
      }
    }
    | SELECT expression_list {
      $$ = new ParsedSqlNode(SCF_CALC);
      if($2 != nullptr){
        $$->calc.expressions.swap(*$2);
        delete $2;
      }
    }
    ;

order_by_stmt:
    /* empty */
    {
      $$ = nullptr;
    }
    | ORDER BY order_by_list
    {
      $$ = $3;
    }
    ;

order_by_list:
    order_by
    {
      $$ = new std::vector<std::pair<RelAttrSqlNode *, bool>>;
      $$->push_back(*$1);
      delete $1;
    }
    | order_by COMMA order_by_list
    {
      if($3 != nullptr){
        $$ = $3;
      }
      else{
        $$ = new std::vector<std::pair<RelAttrSqlNode *, bool>>;
      }
      // 要确保顺序的正确
      $$->insert($$->begin(), *$1);
      delete $1;
    }
    ;
order_by:
    rel_attr ASC 
    {
      $$ = new std::pair<RelAttrSqlNode *, bool>($1, true);
    }
    |rel_attr DESC 
    {
      $$ = new std::pair<RelAttrSqlNode *, bool>($1, false);
    }
    |rel_attr 
    {
      // 默认应该是升序
      $$ = new std::pair<RelAttrSqlNode *, bool>($1, true);
    }
    ;

inner_join_list:
    INNER JOIN relation alias_stmt on_condition {
      $$ = new InnerJoinSqlNode();
      if($4 == nullptr){
        std::pair<std::string, std::string> s_tmp($3, $3);
        $$->relations_and_aliases.push_back(s_tmp);
      }
      else{
        std::pair<std::string, std::string> s_tmp($3, $4);
        $$->relations_and_aliases.push_back(s_tmp);
        free($4);
      }
      free($3);
      if($5 != nullptr){
        for (unsigned i = 0; i < $5->size(); i++) {
          $$->conditions.push_back(std::move((*$5)[i]));
        }
        delete $5;
      }
    }
    | INNER JOIN relation alias_stmt on_condition inner_join_list {
      if($6 != nullptr){
        $$ = $6;
      }
      else{
        $$ = new InnerJoinSqlNode();
      }
      if($4 == nullptr){
        std::pair<std::string, std::string> s_tmp($3, $3);
        $$->relations_and_aliases.insert($$->relations_and_aliases.begin(), s_tmp);
      }
      else{
        std::pair<std::string, std::string> s_tmp($3, $4);
        $$->relations_and_aliases.insert($$->relations_and_aliases.begin(), s_tmp);
        free($4);
      }
      free($3);
      if($5 != nullptr){
        for (unsigned i = 0; i < $5->size(); i++) {
          $$->conditions.push_back(std::move((*$5)[i]));
        }
        //delete $4;
      }
    }
    ;

on_condition:
    /* empty */
    {
      $$ = nullptr;
    }
    | ON condition_list {
      $$ = std::move($2);
    }
    ;

calc_stmt:
    CALC expression_list
    {
      $$ = new ParsedSqlNode(SCF_CALC);
      $$->calc.expressions.swap(*$2);
      delete $2;
    }
    ;

expression_list:
    expression alias_stmt
    {
      $$ = new std::vector<std::unique_ptr<Expression>>;
      if($2 != nullptr){
        $1->set_name($2);
        free($2);
      }
      $$->emplace_back($1);
    }
    | expression alias_stmt COMMA expression_list
    {
      if ($4 != nullptr) {
        $$ = $4;
      } else {
        $$ = new std::vector<std::unique_ptr<Expression>>;
      }
      if($2 != nullptr){
        $1->set_name($2);
        free($2);
      }
      $$->emplace($$->begin(), $1);
    }
    ;
expression:
    expression '+' expression {
      $$ = create_arithmetic_expression(ArithmeticExpr::Type::ADD, $1, $3, sql_string, &@$);
    }
    | expression '-' expression {
      $$ = create_arithmetic_expression(ArithmeticExpr::Type::SUB, $1, $3, sql_string, &@$);
    }
    | expression '*' expression {
      $$ = create_arithmetic_expression(ArithmeticExpr::Type::MUL, $1, $3, sql_string, &@$);
    }
    | expression '/' expression {
      $$ = create_arithmetic_expression(ArithmeticExpr::Type::DIV, $1, $3, sql_string, &@$);
    }
    | LBRACE expression RBRACE {
      $$ = $2;
      $$->set_name(token_name(sql_string, &@$));
    }
    | '-' expression %prec UMINUS {
      // 把负号改为0-value
      Value v(0);
      Expression *left = static_cast<Expression *>(new ValueExpr(v));
      $$ = create_arithmetic_expression(ArithmeticExpr::Type::SUB, left, $2, sql_string, &@$);
    }
    | value {
      $$ = new ValueExpr(*$1);
      $$->set_name(token_name(sql_string, &@$));
      delete $1;
    }
    | rel_attr {
      RelAttrSqlNode *node = $1;
      $$ = new UnboundFieldExpr(node->relation_name, node->attribute_name);
      $$->set_name(token_name(sql_string, &@$));
      delete $1;
    }
    | '*' {
      $$ = new StarExpr();
    }
    | ID DOT '*' {
      $$ = new StarExpr($1);
      free($1);
    }
    | COUNT LBRACE expression RBRACE {
      const char *name = "count";
      $$ = create_aggregate_expression(name, $3, sql_string, &@$);
    }
    | SUM LBRACE expression RBRACE {
      const char *name = "sum";
      $$ = create_aggregate_expression(name, $3, sql_string, &@$);
    }
    | AVG LBRACE expression RBRACE {
      const char *name = "avg";
      $$ = create_aggregate_expression(name, $3, sql_string, &@$);
    }
    | MAX LBRACE expression RBRACE {
      const char *name = "max";
      $$ = create_aggregate_expression(name, $3, sql_string, &@$);
    }
    | MIN LBRACE expression RBRACE {
      const char *name = "min";
      $$ = create_aggregate_expression(name, $3, sql_string, &@$);
    }
    | COUNT LBRACE expression COMMA expression RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | MAX LBRACE expression COMMA expression RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | MIN LBRACE expression COMMA expression RBRACE  {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | AVG LBRACE expression COMMA expression RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | SUM LBRACE expression COMMA expression RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | COUNT LBRACE RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | MAX LBRACE RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | MIN LBRACE RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | AVG LBRACE RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | SUM LBRACE RBRACE {
      throw std::invalid_argument("aggregation input invalid!");
    }
    | LBRACE select_stmt RBRACE {
      $$ = new SubQueryExpr($2->selection);
      $$->set_name(token_name(sql_string, &@$));
      delete $2;
    }
    | LENGTH_FUNCTION LBRACE expression RBRACE {
      $$ = new LengthExpr($3);
      $$->set_name(token_name(sql_string, &@$));
    }
    | ROUND_FUNCTION LBRACE expression RBRACE {
      $$ = new RoundExpr($3,0);
      $$->set_name(token_name(sql_string, &@$));
    }
    | ROUND_FUNCTION LBRACE expression COMMA NUMBER RBRACE {
      $$ = new RoundExpr($3, $5);
      $$->set_name(token_name(sql_string, &@$));
    }
    | DATE_FORMAT_FUNCTION LBRACE expression COMMA SSS RBRACE {
      $$ = new DateFormatExpr($3, std::string($5));
      $$->set_name(token_name(sql_string, &@$));
      free($5);
    }
    // your code here
    ;

/* rel_attr_list: */
/*     rel_attr { */
/*       if ($$ == nullptr) { */
/*         $$ = new std::vector<RelAttrSqlNode>(); */
/*       } */
/*       printf("执行到了list了\n"); */
/*       if($1 == nullptr){ */
/*         printf("不知道为啥还是空指针？\n"); */
/*       } */
/*       else{ */
/*         printf("这不是空指针啊\n"); */
/*       } */
/*       // 这里不是空指针，而是出现了悬空指针的情况，为什么？是在什么地方把这个内存给释放了？ */
/*       $$->push_back(*$1); */
/*       delete $1; */
/*     } */
/*     | rel_attr COMMA rel_attr_list { */
/*       if($3 != nullptr) { */
/*         $$ = $3; */
/*       } */
/*       else{ */
/*         $$ = new std::vector<RelAttrSqlNode>(); */
/*       } */
/*       $$->push_back(*$1); */
/*       delete $1; */
/*     } */
/*     ; */

rel_attr:
    ID {
      /* printf("果然还是执行这里了！\n"); */
      $$ = new RelAttrSqlNode;
      if($$ == nullptr){
        /* printf("都New了怎么还空指针？\n"); */
      }
      std::string s($1);
      $$->attribute_name = s;
      /* printf("------------------%s\n", $1); */
      /* printf("------------------%s\n", $$->attribute_name.c_str()); */
      free($1);
    }
    | ID DOT ID {
      $$ = new RelAttrSqlNode;
      std::string s1($1);
      std::string s3($3);
      $$->relation_name  = s1;
      $$->attribute_name = s3;
      free($1);
      free($3);
    }
    ;

relation:
    ID {
      $$ = $1;
    }
    ;
rel_list:
    relation alias_stmt{
      // $$ = new std::vector<std::string>();
      $$ = new std::vector<std::pair<std::string, std::string>>;
      if($2 == nullptr){
        $$->push_back(std::make_pair(std::string($1), std::string($1)));
      }
      else{
        $$->push_back(std::make_pair(std::string($1), std::string($2)));
        free($2);
      }
      free($1);
    }
    | relation alias_stmt COMMA rel_list {
      if ($4 != nullptr) {
        $$ = $4;
      } else {
        // $$ = new std::vector<std::string>;
        $$ = new std::vector<std::pair<std::string, std::string>>;
      }
      if($2 == nullptr){
        $$->insert($$->begin(), std::make_pair(std::string($1), std::string($1)));
      }
      else{
        $$->insert($$->begin(), std::make_pair(std::string($1), std::string($2)));
        free($2);
      }
      free($1);
    }
    ;

where:
    /* empty */
    {
      $$ = nullptr;
    }
    | WHERE condition_list {
      $$ = $2;  
    }
    ;
condition_list:
    /* empty */
    {
      $$ = nullptr;
    }
    | condition {
      $$ = new std::vector<ConditionSqlNode>;
      $$->emplace_back(std::move(*$1));
      delete $1;
    }
    | condition conjunction_op condition_list {
      $$ = $3;
      $1->conjunction_type = *$2;
      // 这里要把新的condition放在前面，因为后边的condition_list是先解析的
      $$->insert($$->begin(), std::move(*$1));
      delete $2;
      delete $1;
    }
    ;
conjunction_op:
    AND {
      $$ = new bool(true);
    }
    | OR {
      $$ = new bool(false);
    }
    ;

alias_stmt:
    /* empty */
    {
      $$ = nullptr;
    }
    | ID {
      $$ = $1;
    }
    | AS ID {
      $$ = $2;
    }
    ;

condition:
    // rel_attr comp_op value
    // {
    //   $$ = new ConditionSqlNode;
    //   $$->left_is_attr = 1;
    //   $$->left_attr = *$1;
    //   $$->right_is_attr = 0;
    //   $$->right_value = *$3;
    //   $$->comp = $2;
    //
    //   delete $1;
    //   delete $3;
    // }
    // | value comp_op value 
    // {
    //   $$ = new ConditionSqlNode;
    //   $$->left_is_attr = 0;
    //   $$->left_value = *$1;
    //   $$->right_is_attr = 0;
    //   $$->right_value = *$3;
    //   $$->comp = $2;
    //
    //   delete $1;
    //   delete $3;
    // }
    // | rel_attr comp_op rel_attr
    // {
    //   $$ = new ConditionSqlNode;
    //   $$->left_is_attr = 1;
    //   $$->left_attr = *$1;
    //   $$->right_is_attr = 1;
    //   $$->right_attr = *$3;
    //   $$->comp = $2;
    //
    //   delete $1;
    //   delete $3;
    // }
    // | value comp_op rel_attr
    // {
    //   $$ = new ConditionSqlNode;
    //   $$->left_is_attr = 0;
    //   $$->left_value = *$1;
    //   $$->right_is_attr = 1;
    //   $$->right_attr = *$3;
    //   $$->comp = $2;
    //
    //   delete $1;
    //   delete $3;
    // }
    expression comp_op expression
    {
      $$ = new ConditionSqlNode;
      $$->left_is_attr = 0;
      $$->right_is_attr = 0;
      $$->comp = $2;
      $$->left_expr = std::unique_ptr<Expression>($1);
      $$->right_expr = std::unique_ptr<Expression>($3);
    }
    | expression IN LBRACE select_stmt RBRACE
    {
      $$ = new ConditionSqlNode;
      $$->left_is_attr = 1;
      $$->left_expr = std::unique_ptr<Expression>($1);
      $$->right_is_attr = 0;
      $$->comp = IN_OP;

      // Create a SubQueryExpr and assign it to the simple_sub_query smart pointer
      $$->right_expr = std::unique_ptr<Expression>(new SubQueryExpr($4->selection));

      delete $4;
    }
    | expression NOT IN LBRACE select_stmt RBRACE
    {
      $$ = new ConditionSqlNode;
      $$->left_is_attr = 1;
      $$->left_expr = std::unique_ptr<Expression>($1);
      $$->right_is_attr = 0;
      $$->comp = NOT_IN_OP;

      // Create a SubQueryExpr and assign it to the simple_sub_query smart pointer
      $$->right_expr = std::unique_ptr<Expression>(new SubQueryExpr($5->selection));

      delete $5;
    }
    // | expression comp_op LBRACE select_stmt RBRACE
    // {
    //   $$ = new ConditionSqlNode;
    //   $$->left_is_attr = 1;
    //   $$->left_expr = std::unique_ptr<Expression>($1);
    //   $$->right_is_attr = 0;
    //   $$->comp = $2;
    //
    //   // Create a SubQueryExpr and assign it to the simple_sub_query smart pointer
    //   $$->simple_sub_query = std::unique_ptr<Expression>(new SubQueryExpr($4->selection));
    //
    //   delete $4;
    // }
    // | LBRACE select_stmt RBRACE comp_op expression
    // {
    // // 这里的顺序应该反过来，因为后边还有具有方向的比较运算符
    //   $$ = new ConditionSqlNode;
    //   $$->left_is_attr = 0;
    //   $$->right_expr = std::unique_ptr<Expression>($5);
    //   $$->right_is_attr = 1;
    //   $$->comp = $4;
    //
    //   // Create a SubQueryExpr and assign it to the simple_sub_query smart pointer
    //   $$->simple_sub_query = std::unique_ptr<Expression>(new SubQueryExpr($2->selection));
    //
    //   delete $2;
    // }
    | expression IN LBRACE expression_list RBRACE
    {
      $$ = new ConditionSqlNode;
      $$->left_is_attr = 1;
      $$->left_expr = std::unique_ptr<Expression>($1);
      $$->right_is_attr = 0;
      $$->comp = IN_OP;
      // 这里取出values用来初始化TupleExpr
      std::vector<Value> values;
      if($4 != nullptr){
        for(unsigned i = 0;i < $4->size();i++){
          Value value_tmp;
          Expression *expr_tmp = (*$4)[i].get();
          expr_tmp->try_get_value(value_tmp);
          values.push_back(value_tmp);
        }
      }
      $$->right_expr = std::unique_ptr<Expression>(new TupleExpr(values));

      delete $4;
    }
    | expression NOT IN LBRACE expression_list RBRACE
    {
      $$ = new ConditionSqlNode;
      $$->left_is_attr = 1;
      $$->left_expr = std::unique_ptr<Expression>($1);
      $$->right_is_attr = 0;
      $$->comp = NOT_IN_OP;
      // 这里取出values用来初始化TupleExpr
      std::vector<Value> values;
      if($5 != nullptr){
        for(unsigned i = 0;i < $5->size();i++){
          Value value_tmp;
          Expression *expr_tmp = (*$5)[i].get();
          expr_tmp->try_get_value(value_tmp);
          values.push_back(value_tmp);
        }
      }
      $$->right_expr = std::unique_ptr<Expression>(new TupleExpr(values));

      delete $5;
    }
    | EXISTS LBRACE select_stmt RBRACE
    {
      $$ = new ConditionSqlNode;
      $$->left_is_attr = 0;
      $$->right_is_attr = 0;
      $$->comp = EXISTS_OP;

      // Create a SubQueryExpr and assign it to the simple_sub_query smart pointer
      $$->right_expr = std::unique_ptr<Expression>(new SubQueryExpr($3->selection));

      delete $3;
    }
    | NOT EXISTS LBRACE select_stmt RBRACE
    {
      $$ = new ConditionSqlNode;
      $$->left_is_attr = 0;
      $$->right_is_attr = 0;
      $$->comp = NOT_EXISTS_OP;

      // Create a SubQueryExpr and assign it to the simple_sub_query smart pointer
      $$->right_expr = std::unique_ptr<Expression>(new SubQueryExpr($4->selection));

      delete $4;
    }
    ;

comp_op:
      EQ { $$ = EQUAL_TO; }
    | LT { $$ = LESS_THAN; }
    | GT { $$ = GREAT_THAN; }
    | LE { $$ = LESS_EQUAL; }
    | GE { $$ = GREAT_EQUAL; }
    | LIKE { $$ = LIKE_WITH; }
    | NOT LIKE { $$ = NOT_LIKE_WITH; }
    | NE { $$ = NOT_EQUAL; }
    | IS_ { $$ = IS_NULL; }
    | IS_ NOT { $$ = IS_NOT_NULL; }
    ;

// your code here
group_by:
    /* empty */
    {
      $$ = nullptr;
    }
    | GROUP BY group_by_list {
      $$ = new GroupBySqlNode;
      $$->group_by = $3;
      $$->having = nullptr;
    }
    | GROUP BY group_by_list HAVING condition_list {
      $$ = new GroupBySqlNode;
      $$->group_by = $3;
      $$->having = $5;
    }
    ;

group_by_list:
    rel_attr {
      $$ = new std::vector<unique_ptr<Expression>>;
      std::unique_ptr<Expression> unbound_field_expr(static_cast<Expression *>(new UnboundFieldExpr($1->relation_name, $1->attribute_name)));
      $$->emplace_back(std::move(unbound_field_expr));
      delete $1;
    }
    | rel_attr COMMA group_by_list {
      if ($3 != nullptr) {
        $$ = $3;
      } else {
        $$ = new std::vector<unique_ptr<Expression>>;
      }
      std::unique_ptr<Expression> unbound_field_expr(static_cast<Expression *>(new UnboundFieldExpr($1->relation_name, $1->attribute_name)));
      $$->insert($$->begin(), std::move(unbound_field_expr));
      delete $1;
    }
    ;

load_data_stmt:
    LOAD DATA INFILE SSS INTO TABLE ID 
    {
      char *tmp_file_name = common::substr($4, 1, strlen($4) - 2);
      
      $$ = new ParsedSqlNode(SCF_LOAD_DATA);
      $$->load_data.relation_name = $7;
      $$->load_data.file_name = tmp_file_name;
      free($7);
      free(tmp_file_name);
    }
    ;

explain_stmt:
    EXPLAIN command_wrapper
    {
      $$ = new ParsedSqlNode(SCF_EXPLAIN);
      $$->explain.sql_node = std::unique_ptr<ParsedSqlNode>($2);
    }
    ;

set_variable_stmt:
    SET ID EQ value
    {
      $$ = new ParsedSqlNode(SCF_SET_VARIABLE);
      $$->set_variable.name  = $2;
      $$->set_variable.value = *$4;
      free($2);
      delete $4;
    }
    ;

opt_semicolon: /*empty*/
    | SEMICOLON
    ;
%%
//_____________________________________________________________________
extern void scan_string(const char *str, yyscan_t scanner);

int sql_parse(const char *s, ParsedSqlResult *sql_result) {
  yyscan_t scanner;
  yylex_init(&scanner);
  scan_string(s, scanner);
  int result = yyparse(s, sql_result, scanner);
  yylex_destroy(scanner);
  return result;
}
